package de.akabahn.ebd.dbd;

import java.util.List;

import de.akabahn.ebd.comm.dbd.DBDParameter;

/**
 * Interface for the "DBDAdapter" application, implementations of this interface
 * are created using the <code>DBDAdapterFactory</code>.
 * 
 * @author Peter Eimann
 * @since 0.2
 * @version 1.0
 * @see DBDAdapterFactory
 */
public interface DBDAdapter {

	/**
	 * Establish the connection to the DBD server and set the life cycle status
	 * of the instance to <code>started</code>.
	 * 
	 * @throws DBDException
	 */
	public abstract void start() throws DBDException;

	/**
	 * Disconnect from the DBD server and set the life cycle status of the
	 * instance to <code>stopped</code>.
	 * 
	 * @throws DBDException
	 */
	public abstract void stop() throws DBDException;

	/**
	 * Return if the current life cycle status is <code>started</code> or not
	 * 
	 * @return <code>true</code> if the life cycle status is
	 *         <code>started</code>
	 */
	public abstract boolean isStarted();

	/**
	 * Reload the list of all known variables from the DBD server. Needs to be
	 * called if the cached list of DBD variables needs to be updated.
	 */
	public abstract void reloadDBDVariables();

	/**
	 * List all variables that are currently known in the DBD server for
	 * requested (or all) stations.
	 * 
	 * @param stationNumbers
	 *            A list of station numbers for which the variables will be
	 *            returned (if <code>null</code> is passed, all variables are
	 *            returned)
	 * @return The list of variables for the passed station numbers
	 * @throws DBDException
	 */
	public abstract List<String> listAvailableVariables(String[] stationNumbers) throws DBDException;

	/**
	 * List all switches that are currently known in the DBD server for
	 * requested (or all) stations. *
	 * 
	 * @param stationNumbers
	 *            A list of station numbers for which the switches will be
	 *            returned (if <code>null</code> is passed, all switches are
	 *            returned)
	 * @return The list of switches for the passed station numbers
	 * @throws DBDException
	 */
	public abstract List<String> listAvailableSwitches(String[] stationNumbers) throws DBDException;

	/**
	 * Query the current value of the DBD variable with the passed
	 * <code>name</code>.
	 * 
	 * @param name
	 *            The name of the variable to query
	 * @return The current value of the variable wrapped in a
	 *         <code>DBDParameter</code>
	 * @throws DBDException
	 * @see #query(String, Class)
	 */
	public abstract DBDParameter query(String name) throws DBDException;

	/**
	 * Query the current value of the DBD variable with the passed
	 * <code>name</code> and return the response as the passed <code>type</code>
	 * . See the documentation of the implementation class for a list of
	 * supported types.
	 * 
	 * @param name
	 *            The name of the variable to query
	 * @param type
	 *            The type of the response object
	 * @return The current value of the variable represented by an object of the
	 *         passed type (maybe <code>null</code> if no response has been
	 *         received)
	 * @throws DBDException
	 */
	public abstract <T> T query(String name, Class<T> type) throws DBDException;

	/**
	 * Set the DBD variable <code>name</code> to the passed <code>value</code>.
	 * 
	 * @param name
	 *            The name of the variable to set
	 * @param value
	 *            The new value of the variable
	 * @throws DBDException
	 */
	public abstract void set(String name, int value) throws DBDException;

	/**
	 * Set the DBD variable <code>name</code>, which refers to a switch, to the
	 * passed position.
	 * 
	 * @param name
	 *            The name of the variable (switch) to set
	 * @param pos
	 *            The new position of the switch
	 * @throws DBDException
	 */
	public abstract void set(String name, SwitchPosition pos) throws DBDException;

	/**
	 * Set the DBD variable <code>name</code>, which refers to a signal, to the
	 * passed signal aspect.
	 * 
	 * @param name
	 *            The name of the variable (signal) to set
	 * @param signal
	 *            The new signal aspect to show
	 * @throws DBDException
	 */
	public abstract void set(String name, DBDSignal signal) throws DBDException;

	/**
	 * Force the variable <code>name</code> to the passed <code>value</code>.
	 * 
	 * @param name
	 *            The name of the variable
	 * @param value
	 *            The value to force the variable to (write protection)
	 * @throws DBDException
	 */
	public abstract void force(String name, int value) throws DBDException;

	/**
	 * Unforce the variable <code>name</code> and remove the write protection.
	 * 
	 * @param name
	 *            The name of the variable
	 * @throws DBDException
	 */
	public abstract void unforce(String name) throws DBDException;

	/**
	 * Subscribe to the variable with the passed <code>name</code> and pass the
	 * <code>DBDSubscriptionListener</code> that will be notified when this
	 * variable has changed.<br>
	 * 
	 * @param name
	 *            The name of the variable to subscribe to
	 * @param listener
	 *            The subscription listener that is called (via the
	 *            <code>onChange()</code> method) when the variable has changed
	 * @throws DBDException
	 */
	public abstract void subscribe(String name, DBDSubscriptionListener listener) throws DBDException;

	/**
	 * Unsubscribe <b>all</b> listeners from the variable with the passed <code>name</code>.
	 *
	 * @param name
	 *            The name of the variable to unsubscribe from
	 */
	public abstract void unsubscribe(String name);

	/**
	 * Unsubscribe a specific <code>listener</code> from the variable with the
	 * passed <code>name</code>.
	 *
	 * @param name
	 *            The name of the variable to unsubscribe from
	 * @param listener
	 *            The subscription listener to be removed
	 * @author moschlar
	 * @since 2.2.0
	 * @version 2.2.0
	 */
	public abstract void unsubscribe(String name, DBDSubscriptionListener listener);

}